Add Quovadis suport, courtesy Bruce Thompson, bruce at otherother.com.
authorrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Mon, 30 Jun 2003 05:41:29 +0000 (05:41 +0000)
committerrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Mon, 30 Jun 2003 05:41:29 +0000 (05:41 +0000)
gpsbabel/Makefile
gpsbabel/README
gpsbabel/quovadis.c [new file with mode: 0644]
gpsbabel/quovadis.h [new file with mode: 0644]
gpsbabel/reference/quovadis.gpu [new file with mode: 0644]
gpsbabel/reference/quovadis.pdb [new file with mode: 0644]

index 7f960583d384c1a6a3d39c3654f4c25fb0621d71..eec76d66f24248f9768c2e3801d3c909091acca7 100644 (file)
@@ -1,11 +1,11 @@
 # add -DDEBUG_MEM to turn on memory allocation logging
-CFLAGS=$(EXTRA_CFLAGS) -g -Icoldsync
+CFLAGS=$(EXTRA_CFLAGS) -g -Icoldsync 
 INSTALL_TARGETDIR=/usr/local/
 
 FMTS=magproto.o gpx.o geo.o mapsend.o mapsource.o \
        gpsutil.o pcx.o cetus.o copilot.o gpspilot.o magnav.o \
        psp.o holux.o garmin.o tmpro.o tpg.o \
-       xcsv.o gcdb.o tiger.o internal_styles.o easygps.o
+       xcsv.o gcdb.o tiger.o internal_styles.o easygps.o quovadis.o
 
 FILTERS=position.o duplicate.o
 
@@ -71,6 +71,7 @@ release:
 # Machine generated from here down.   
 
 cetus.o: cetus.c defs.h queue.h coldsync/palm.h coldsync/pdb.h
+quovadis.o: quovadis.c defs.h queue.h coldsync/palm.h coldsync/pdb.h quovadis.h
 copilot.o: copilot.c defs.h queue.h coldsync/palm.h coldsync/pdb.h
 csv_util.o: csv_util.c defs.h queue.h csv_util.h
 duplicate.o: duplicate.c defs.h queue.h
index 4ab60563963db4e3ce58c8733e0d66165dfefbb6..247492e4e6ceff45244c914892c660cadd73b673 100644 (file)
@@ -171,6 +171,31 @@ THE FORMATS
        files for that program.   It hasn't been exhaustively tested, but 
        has seemed fine on every input and output we've tried.
 
+    QUOVADIS
+
+       QuoVadis for Palm OS (http://www.marcosoft.com/) is a program
+       for Palm/OS. Working with record definitions provided by
+       MarcoSoft and further experimentation by Bruce Thompson and
+       "Fuzzy" from the Geocaching Forums to nail down the format
+       precisely.
+
+       Should work fine for import and export.
+
+       One thing of note, QuoVadis stores all waypoints in a single
+       Palm Database without using categories. This means that it may
+       be difficult to keep personal waypoints separate from
+       generated waypoints. What Bruce recommends is taking the
+       QuoVadisMarkerDB.PDB file synced down from your Palm Powered
+       device and extract the waypoints you personally set to a GPX
+       file. Then using GPSBabel's joining capabilities generate a
+       new PDB file from the personal file and the other waypoint
+       files of interest.
+
+       Currently the selection of icons to display and the scale at
+       which to display them is hardcoded. Also there is no support
+       for notes associated with waypoints. This will be addressed in
+       a future revision.
+
     GPSPILOT
 
        The file format for GPSPILOT (http://www.gpspilot.com) was provided
diff --git a/gpsbabel/quovadis.c b/gpsbabel/quovadis.c
new file mode 100644 (file)
index 0000000..669786c
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+    Read and write QuoVadis files.
+
+    Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "quovadis.h"
+
+static FILE *file_in;
+static FILE *file_out;
+static const char *out_fname;
+struct pdb *opdb;
+
+static int ct;
+static char* rec_ptr = NULL;
+static char* current_rec = NULL;
+static int rec_index = 0;
+
+static char *dbname = NULL;
+
+static
+arglist_t quovadis_args[] = {
+       {"dbname", &dbname, "Database name"},
+       {0, 0, 0}
+};
+
+static struct qv_icon_mapping mapping[] = {
+    { gt_unknown, QUESTION_ICON },
+    { gt_traditional, HOSPITAL_ICON },
+    { gt_multi, DOCUMENT_ICON },
+    { gt_virtual, CAMERA_ICON },
+    { gt_letterbox, MAILBOX_ICON },
+    { gt_event, MEETING_ICON },
+    { gt_suprise, GIFTSHOP_ICON },
+};
+
+#define num_mappings (sizeof(mapping) / sizeof(struct qv_icon_mapping))
+
+static geocache_type icon_to_wpt(int   icon_bitmap) {
+    int i;
+
+    for (i = 0; i < num_mappings; i++) {
+       if (icon_bitmap == mapping[i].bitmap_id) {
+           return mapping[i].gc_type;
+       }
+    }
+    return gt_unknown;
+}
+
+static int wpt_to_icon(geocache_type   type) {
+    int i;
+
+    for (i = 0; i < num_mappings; i++) {
+       if (type == mapping[i].gc_type) {
+           return mapping[i].bitmap_id;
+       }
+    }
+    return QUESTION_ICON;
+}
+
+static void
+docopy(char*           dest,
+       const char*     src,
+       const int       size)
+{
+    int i;
+    for (i = 0; i < size; i++) {
+       dest[i] = src[i];
+    }
+}
+
+static void
+rd_init(const char *fname, const char *args)
+{
+       file_in = fopen(fname, "rb");
+       if (file_in == NULL) {
+               fatal(MYNAME ": Cannot open %s for reading\n", fname);
+       }
+}
+
+static void
+rd_deinit(void)
+{
+       fclose(file_in);
+       if ( dbname ) {
+           xfree(dbname);
+           dbname = NULL;
+       }
+}
+
+static void
+wr_init(const char *fname, const char *args)
+{
+       file_out = fopen(fname, "wb");
+       out_fname = fname;
+       if (file_out == NULL) {
+               fatal(MYNAME ": Cannot open %s for writing\n", fname);
+       }
+}
+
+static void
+wr_deinit(void)
+{
+       fclose(file_out);
+       if ( dbname ) {
+           xfree(dbname);
+           dbname = NULL;
+       }
+}
+
+static void
+data_read(void)
+{
+    struct record *rec;
+    struct pdb *pdb;
+    struct pdb_record *pdb_rec;
+    int        i;
+
+    if (NULL == (pdb = pdb_Read(fileno(file_in)))) {
+       fatal(MYNAME ": pdb_Read failed\n");
+    }
+
+    if ((pdb->creator != MYCREATOR) || (pdb->type != MYTYPE)) {
+       fatal(MYNAME ": Not a QuoVadis file.\n");
+    }
+       
+    /* Ignore the first record, it contains one zero byte */
+    for(pdb_rec = pdb->rec_index.rec->next; pdb_rec; pdb_rec=pdb_rec->next) {
+       int num_recs = pdb_rec->data_len / sizeof(struct record);
+       for (i = 0; i < num_recs; i++) {
+           waypoint *wpt_tmp;
+
+           wpt_tmp = xcalloc(sizeof(*wpt_tmp),1);
+
+           rec = (struct record *)
+               &(pdb_rec->data[i * sizeof(struct record)]);
+
+           wpt_tmp->position.longitude.degrees =
+               (be_read32(&rec->longitude) / 1000000.0) - 180.0; 
+           wpt_tmp->position.latitude.degrees =
+               90.0 - (be_read32(&rec->latitude) / 1000000.0);
+           wpt_tmp->shortname = xstrdup(rec->name);
+
+           wpt_tmp->gc_data.type =
+               icon_to_wpt(be_read16(&rec->icon_bitmap));
+
+           waypt_add(wpt_tmp);
+       }
+    } 
+    free_pdb(pdb);
+}
+
+
+static void
+quovadis_writewpt(waypoint *wpt)
+{
+    struct record *rec;
+    int        i;
+
+    if (current_rec == NULL) {
+       char dummy = 0;
+       struct pdb_record *pdb_rec;
+       pdb_rec = new_Record(0, 0, ct++, 1, &dummy);
+       if (pdb_rec == NULL) {
+           fatal(MYNAME ": libpdb couldn't create record\n");
+       }
+       if (pdb_AppendRecord(opdb, pdb_rec)) {
+           fatal(MYNAME ": libpdb couldn't append record\n");
+       }
+
+       current_rec = xcalloc(MAXCHUNKSIZE, 1);
+       rec_index = 0;
+       rec_ptr = current_rec;
+    }
+
+    rec = xcalloc(sizeof(*rec),1);
+
+    be_write32(&rec->longitude, (wpt->position.longitude.degrees +
+                                180.0) * 1000000.0);
+    be_write32(&rec->latitude, (90.0 - wpt->position.latitude.degrees) * 1000000.0);
+    if ( wpt->shortname ) {
+       strncpy(rec->name, wpt->shortname, 32 );
+       rec->name[31] = '\0';
+    }
+    else {
+       rec->name[0] = '\0';
+    }
+    be_write16(&rec->icon_bitmap, wpt_to_icon(wpt->gc_data.type));
+    be_write32(&rec->note_id, 0);
+    rec->name_scale = DEFAULT_NAME_SCALE;
+    rec->icon_scale = DEFAULT_ICON_SCALE;
+    for (i = 0; i < 7; i++) {
+       rec->reserved[i] = 0;
+    }
+
+    docopy(rec_ptr, (const char*)rec, sizeof(*rec));
+    rec_ptr += sizeof(*rec);
+    rec_index += 1;
+    xfree(rec);
+
+    if (rec_index == MAXRECORDS) {
+       fatal(MYNAME ": cannot store more than %d records at this time.\n",
+             MAXRECORDS);
+    }
+}
+
+struct hdr{
+       char *wpt_name; 
+       waypoint *wpt;
+};
+
+static
+int 
+compare(const void *a, const void *b)
+{
+       const struct hdr *wa = a;
+       const struct hdr *wb = b;
+
+       return strcmp(wa->wpt->shortname, wb->wpt->shortname);
+}
+
+static void
+data_write(void)
+{
+       int i, ct = waypt_count();
+       struct hdr *htable, *bh;
+        queue *elem, *tmp;
+       extern queue waypt_head;
+        waypoint *waypointp;
+
+       if (NULL == (opdb = new_pdb())) { 
+               fatal (MYNAME ": new_pdb failed\n");
+       }
+
+       if ( dbname ) {
+           strncpy( opdb->name, dbname, PDB_DBNAMELEN );
+       }
+       else {
+           strncpy(opdb->name, "QuoVadisMarkerDB", PDB_DBNAMELEN);
+       }
+       opdb->name[PDB_DBNAMELEN-1] = 0;
+       opdb->attributes = PDB_ATTR_BACKUP;
+       opdb->ctime = opdb->mtime = time(NULL) + 2082844800U;
+       opdb->type = MYTYPE;  /* CWpt */
+       opdb->creator = MYCREATOR; /* cGPS */
+       opdb->version = 1;
+
+       /*
+        * All this is to sort by waypoint names before going to QuoVadis.
+        * Turns out plain old strcmp will do the trick...
+        */
+
+       htable = xmalloc(ct * sizeof(*htable));
+       bh = htable;
+
+        QUEUE_FOR_EACH(&waypt_head, elem, tmp) {
+                waypointp = (waypoint *) elem;
+               bh->wpt = waypointp;
+               bh->wpt_name = waypointp->shortname;
+               bh ++;
+       }
+       qsort(htable, ct, sizeof(*bh), compare);
+
+       for (i=0;i<ct;i++) {
+               quovadis_writewpt(htable[i].wpt);
+       }
+
+       if (rec_index != 0) {
+           struct pdb_record* pdb_rec;
+           pdb_rec = new_Record(0, 0, ct++, rec_index *
+                                sizeof(struct record), current_rec);
+       
+           if (pdb_rec == NULL) {
+               fatal(MYNAME ": libpdb couldn't create record\n");
+           }
+
+           if (pdb_AppendRecord(opdb, pdb_rec)) {
+               fatal(MYNAME ": libpdb couldn't append record\n");
+           }
+       }
+       xfree(current_rec);
+
+       pdb_Write(opdb, fileno(file_out));
+       xfree(htable);
+}
+
+
+ff_vecs_t quovadis_vecs = {
+       rd_init,
+       wr_init,
+       rd_deinit,
+       wr_deinit,
+       data_read,
+       data_write,
+       quovadis_args
+};
diff --git a/gpsbabel/quovadis.h b/gpsbabel/quovadis.h
new file mode 100644 (file)
index 0000000..19f7c88
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+    Definitions for QuoVadis files.
+
+    Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+#ifndef __quovadis_h__
+#define __quovadis_h__
+
+#include "defs.h"
+#include "coldsync/palm.h"
+#include "coldsync/pdb.h"
+
+#define MYNAME "QuoVadis"
+#define MYTYPE  0x51564D52     /* QVMR */
+#define MYCREATOR 0x51554F56   /* QUOV */
+
+#define MAXCHUNKSIZE   0x10000 /* 64k Chunk max */
+
+struct record {
+    char               name[32];
+    pdb_32             longitude; /* Scaled. (degrees + 180.0) * 1e6 */
+    pdb_32             latitude; /* Scaled. (degrees + 90.0) * 1e6 */
+    pdb_16             icon_bitmap; /* Valid range: 0 - 47 */
+    pdb_32             note_id; /* Global ID of note in NotesDB. Not
+                                   supported yet */
+    char               name_scale; /* Map scale to display the
+                                      name. Valid range 15-26. 15 =>
+                                      18.12 miles, 26 => 46 feet */
+    char               icon_scale; /* As above. */
+    unsigned char      reserved[8];
+};
+
+struct qv_icon_mapping {
+    const geocache_type                gc_type;
+    const int                  bitmap_id;
+};
+
+/* Icon Types */
+#define QUESTION_ICON          0
+#define RESTARAUNT_ICON                1
+#define BAR_ICON               2
+#define HOTEL_ICON             3
+#define PHONE_ICON             4
+#define HOSPITAL_ICON          5
+#define CHURCH_ICON            6
+#define AIRPORT_ICON           7
+#define TRAIN_ICON             8
+#define BUS_ICON               9
+#define CAR_ICON               10
+#define WRENCH_ICON            11
+#define GASOLINE_ICON          12
+#define PARKING_ICON           13
+#define MAIL_ICON              14
+#define MAILBOX_ICON           15
+#define CLOCK_ICON             16
+#define FLAG_ICON              17
+#define LIBRARY_ICON           18
+#define BUILDINGS_ICON         19
+#define RELIGION_ICON          20
+#define DOCUMENT_ICON          21
+#define ANIMAL_ICON            22
+#define CAMERA_ICON            23
+#define MOVIE_ICON             24
+#define MUSIC_ICON             25
+#define MEETING_ICON           26
+#define RESTROOM_ICON          27
+#define FAMILY_ICON            28
+#define TELEVISION_ICON                29
+#define SAILING_ICON           30
+#define GOLF_ICON              31
+#define WORKOUT_ICON           32
+#define CYCLING_ICON           33
+#define JOGGING_ICON           34
+#define CAMPING_ICON           35
+#define WATER_ICON             36
+#define FOREST_ICON            37
+#define GIFTSHOP_ICON          38
+#define BABY_ICON              39
+#define LOVE_ICON              40
+#define CEMETARY_ICON          41
+#define COMPUTER_ICON          42
+#define MONEY_ICON             43
+#define LEFT_ARROW_ICON                44
+#define RIGHT_ARROW_ICON       45
+#define DOWN_ARROW_ICON                46
+#define UP_ARROW_ICON          47
+
+/* Scale Values */
+#define SCALE_18_12MI  15
+#define SCALE_9_06MI   16
+#define SCALE_4_53MI   17
+#define SCALE_2_26MI   18
+#define SCALE_1_13MI   19
+#define SCALE_0_56MI   20
+#define SCALE_0_28MU   21
+#define SCALE_747FT    22
+#define SCALE_373FT    23
+#define SCALE_186FT    24
+#define SCALE_93FT     25
+#define SCALE_46FT     26
+
+#define MAXRECORDS     (MAXCHUNKSIZE / sizeof(struct record))
+/*#define MAXRECORDS   100*/
+#define DEFAULT_ICON_BITMAP    QUESTION_ICON
+#define DEFAULT_NAME_SCALE     SCALE_2_26MI
+#define DEFAULT_ICON_SCALE     SCALE_18_12MI
+
+#endif
diff --git a/gpsbabel/reference/quovadis.gpu b/gpsbabel/reference/quovadis.gpu
new file mode 100644 (file)
index 0000000..9dda4ac
--- /dev/null
@@ -0,0 +1,9 @@
+GC1A37   3609.068N 08667.955W 0000000m                                a
+GC1C2B   3599.627N 08662.012W 0000000m                                a
+GC25A9   3603.848N 08664.862W 0000000m                                a
+GC2723   3611.218N 08674.177W 0000000m                                a
+GC2B71   3606.408N 08679.052W 0000000m                                a
+GC309F   3608.777N 08680.973W 0000000m                                a
+GC317A   3605.750N 08689.200W 0000000m                                a
+GC317D   3608.280N 08686.728W 0000000m                                a
+GCEBB    3597.203N 08713.470W 0000000m                                a
diff --git a/gpsbabel/reference/quovadis.pdb b/gpsbabel/reference/quovadis.pdb
new file mode 100644 (file)
index 0000000..ef5e77f
Binary files /dev/null and b/gpsbabel/reference/quovadis.pdb differ